﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AudiPyme.DAL;

namespace AudiPyme.BLL
{
    public class PlanMejoraNegocio
    {
        //Método que sirve para insertar cada iteración de plan de mejora en la BD y devuelve el IdControl que
        //se cumple
        public static int InsertaElementoPlanMejora(RiesgoActivo ElementoPlanMejora, int IdInforme, int iteracion)
        {
            //Recogemos los atributos
            int IdActivo = ElementoPlanMejora.IdActivo;
            //Se elige de las amenazas que provoquen más riesgo al activo, aquella que tenga más controles asociados que no se
            //cumplen o se cumplen parcialmente. De esta forma, se escogerá la amenaza que tiene más posibilidades de producirse
            //al poder aprovechar el mayor número de salvaguardas que la empresa no cumple
            int IdAmenazaMaximosControles = 0;
            int NumeroControlesNoParcMaximo = 0;
            int RiesgoMaxActual = ElementoPlanMejora.MaximoRiesgoActivo;
            int indiceAmenaza = -1;
            for (int i = 0; i < ElementoPlanMejora.NivelRiesgoAmenaza.Count(); i++)
            {
                if (ElementoPlanMejora.NivelRiesgoAmenaza[i].NivelRiesgoActivo == RiesgoMaxActual)
                {
                    if (ElementoPlanMejora.NivelRiesgoAmenaza[i].ControlesNoParc.Count() > NumeroControlesNoParcMaximo)
                    {
                        IdAmenazaMaximosControles = ElementoPlanMejora.NivelRiesgoAmenaza[i].IdAmenaza;
                        NumeroControlesNoParcMaximo = ElementoPlanMejora.NivelRiesgoAmenaza[i].ControlesNoParc.Count;
                        indiceAmenaza = i;
                    }

                }

            }
            int IdAmenazaSelec = IdAmenazaMaximosControles;
            //Como los controles están almacenados por orden (primero aquellos que tienen como respuesta No y después aquellos
            //que tiene como respuesta parcialmente) se escoge el control que más aparezca en la base de conocimiento (anteponiendo los controles
            //con respuesta No a los controles con respuesta Parcialmente
            int IdControl = ControlMasVulnerable(ElementoPlanMejora, IdAmenazaSelec, IdInforme);
            PlanMejoraFactory.InsertaElementoPlanMejora(IdActivo, IdAmenazaSelec, IdControl, IdInforme, iteracion);
            return IdControl;
        }

        //Método que recoge el control que más se repite (y por tanto, con mayor probabilidad de que se genere el riesgo)
        //del activo elegido en ElementoPlanMejora con el IdTipoActivo y Amenaza Seleccionada del mismo
        private static int ControlMasVulnerable(RiesgoActivo ElementoPlanMejora, int IdAmenazaSelec, int IdInforme)
        {
            int IdTipoActivo = ElementoPlanMejora.IdTipoActivo;
            int IdControlMasVulnerableBD = -1;
            int NumeroControlesNoParcMaximo = 0;
            for (int i = 0; i < ElementoPlanMejora.NivelRiesgoAmenaza.Count(); i++)
            {
                //Se recoge el elemento cuyo IdAmenaza corresponda con la Amenaza con mayor riesgo seleccionada
                //anteriormente (IdAmenezaSelec)
                if (ElementoPlanMejora.NivelRiesgoAmenaza[i].IdAmenaza == IdAmenazaSelec)
                {
                    //Al estar la lista de controles de ControlesNoParc ordenados por valor (primero los de respuesta NO
                    //y luego los de respuesta PARC) se coge el primer elemento de la lista para tratar sólo con los controles
                    //que tengan esa respuesta. De esta forma si el primer elemento es NO sólo se recogeran los elementos con respuesta
                    //NO (sin coger elementos con respuesta PARC, ya que generan menos probabilidad de riesgo)
                    //y si el primer elemento es PARC se recogeran todos los elementos de la lista (que tienen respuesta PARC al no haber
                    //elementos con respuesta NO porque el primer elemento es de respuesta PARC y es una lista ordenada por valores como se dijo
                    //anteriormente
                    String Respuesta = ElementoPlanMejora.NivelRiesgoAmenaza[i].ControlesNoParc.First().ValorControl.Trim();
                    //Se recorren la lista de controles hasta los que tengan la misma respuesta que el primer elemento (que es el que marca el numero de elementos a inspeccionar
                    //al estar la lista de controles ordenada por tipos de respuesta (primero todos los controles con NO, seguido de todos los controles con PARC)
                    for (int j = 0; j < ElementoPlanMejora.NivelRiesgoAmenaza[i].ControlesNoParc.Count() && ElementoPlanMejora.NivelRiesgoAmenaza[i].ControlesNoParc[j].ValorControl.Trim().Equals(Respuesta); j++)
                    {
                        int IdControlActual = ElementoPlanMejora.NivelRiesgoAmenaza[i].ControlesNoParc[j].IdControl;
                        //Se calcula el número de veces que aparece el control actual que más veces se repite en la BD 
                        //asociado al Tipo de Activo del activo con mayor riesgo de la iteración
                        int NumeroVecesControlActual = NumeroVecesControlPorTipoActivoBD(IdTipoActivo, IdControlActual);
                        if (NumeroVecesControlActual > NumeroControlesNoParcMaximo)
                        {
                            NumeroControlesNoParcMaximo = NumeroVecesControlActual;
                            IdControlMasVulnerableBD = IdControlActual;
                        }
                    }
                }
            }
            //Si no se ha encontrado control alguno, se recoge el primer control de la lista de controles del activo seleccionado con mayor riesgo
            if (IdControlMasVulnerableBD == -1)
            {
                for (int i = 0; i < ElementoPlanMejora.NivelRiesgoAmenaza.Count(); i++)
                {
                    if (ElementoPlanMejora.NivelRiesgoAmenaza[i].IdAmenaza == IdAmenazaSelec)
                    {
                        IdControlMasVulnerableBD = ElementoPlanMejora.NivelRiesgoAmenaza[i].ControlesNoParc.First().IdControl;
                    }
                }
            }
            return IdControlMasVulnerableBD;

        }

        //Método que devuelve el número de veces que aparece un control asociado a un tipo de activo en la base de conocimiento
        private static int NumeroVecesControlPorTipoActivoBD(int IdTipoActivo, int IdControlActual)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            int NumeroVeces = (from MTAV in agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer
                               join MTAACR in agenteBD.Matriz_TipoActivosAmenazasCriteriosRiesgoEstablecer on MTAV.IdTipoActivo equals MTAACR.IdTipoActivo
                               join MAC in agenteBD.Matriz_Amenazas_ControlesEstablecer on MTAACR.IdAmenaza equals MAC.IdAmenaza
                               where MTAV.IdTipoActivo == IdTipoActivo && MTAACR.IdTipoActivo == IdTipoActivo && MAC.IdControl == IdControlActual && MAC.Actual == true
                               select MAC.IdControl).Count();
            return NumeroVeces;
        }

        //Método que inserta una nueva iteración de Plan de Mejora
        public static int InsertaElementoPlanMejoraFirst(RiesgoActivo ElementoPlanMejora, int IdInforme, int iteracion)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            //Recogemos los atributos
            PlanMejora NuevoElemento = new PlanMejora();
            NuevoElemento.IdInforme = IdInforme;
            NuevoElemento.Orden = iteracion;
            NuevoElemento.IdActivo = ElementoPlanMejora.IdActivo;
            NuevoElemento.IdAmenaza = ElementoPlanMejora.NivelRiesgoAmenaza.First().IdAmenaza;
            NuevoElemento.IdControl = ElementoPlanMejora.NivelRiesgoAmenaza.First().ControlesNoParc.First().IdControl;
            agenteBD.AddToPlanMejoraEstablecer(NuevoElemento);
            agenteBD.SaveChanges();
            return NuevoElemento.IdControl;
        }


        //Algoritmo de plan de mejora
        public static void CalcularPlanMejora(int IdEmpresa, List<RiesgoActivo> MatrizRiesgos, int IdInforme)
        {
            //Inicio Plan Mejora
            //Creamos un entero que nos indica por que iteracion va el Plan de Mejora vamos y servirá
            //como atributo en la tabla PlanMejora
            int control = 0;
            int iteracion = 0;
            //Mientras el activo con mayor nivel de riesgo sea mayor que 1
            while (MatrizRiesgos.First().MaximoRiesgoActivo > 1)
            {
                iteracion++;
                //Recogemos el IdControl que vamos a cambiar para generar la siguiente iteración
                //Este IdControlMaxAmenaza es el Control por el cual la Amenaza puede generar daño al Activo
                //con mayor riesgo en MatrizRiesgos
                int IdControlMaxAmenaza = PlanMejoraNegocio.InsertaElementoPlanMejora(MatrizRiesgos.First(), IdInforme, iteracion);

                //Ahora ponemos el Control IdControlMaxAmenaza a SI en todas sus apariciones en MatrizRiesgos y volvemos a llamar al
                //Algoritmo Calcular MatricesRiesgo
                for (int i = 0; i < MatrizRiesgos.Count(); i++)
                {
                    //Lo que tiene que hacer CambiaValorControl es ir a los atributos
                    //CoberturaControlesAmenazaActivo y CoberturaControlesAmenazaVulnActivo
                    //recorrerlos por ControlesAmenaza y ControlesAmenazaVuln respectivamente
                    //y cambiar el valor de los controles de éstos que tengan el IdControlMaxAmenaza a SI.
                    //Después se crea una nueva iteración a través de Calcular MatricesRiesgo ya que NivelRiesgoAmenaza 
                    //se limpia en cada pasada de CalculaNivelRiesgo y
                    //se nutre de CoberturaControlesAmenazaActivo y CoberturaControlesAmenazaVulnActivo 
                    //que ya se ha cambiado el control que debía cambiar en cada una de las iteraciones
                    MatrizRiesgos[i].CambiaValorControl(IdControlMaxAmenaza);
                    MatrizRiesgos[i].CalculaCoberturaControlesAmenaza();
                    MatrizRiesgos[i].CoberturaControlesAmenazaActivo.Sort();
                    MatrizRiesgos[i].CoberturaControlesAmenazaVulnActivo.Sort();
                    MatrizRiesgos[i].CalculaNivelRiesgo();
                    MatrizRiesgos[i].NivelRiesgoAmenaza.Sort();
                    MatrizRiesgos[i].NivelMaximoRiesgoActivo();
                }
                MatrizRiesgos.Sort();
            }
            control = 0;
            //Una vez que tenemos el Análisis de Riesgos y el Plan de Mejora en la BD. Pasamos los 
            //Activos, Controles y Relaciones de la Empresa a las tablas de Informe para tener una
            //foto de la Empresa que sirva para generar un Informe sobre la situación de la misma
            bool okEmpresa = EmpresaInformeFactory.InsertaEmpresaInforme(IdEmpresa, IdInforme);
            bool okControles = ControlesEmpresaInformeFactory.InsertaControlesEmpresaInforme(IdEmpresa, IdInforme);
            bool okActivos = ActivosInformeFactory.InsertaActivosInforme(IdEmpresa, IdInforme);
            bool okInstTipAmenCrit = InstanciaTipactAmenCritriesgInformeFactory.InsertaInstTipactAmenCritriesg(IdEmpresa, IdInforme);
            bool okInstTipVuln = InstanciaTipactVulnInformeFactory.InsertaInstTipactVulnInforme(IdEmpresa, IdInforme);
        }

    }
}
